package com.cash.app.utils

import android.Manifest
import android.content.Context
import android.content.pm.PackageManager
import android.location.Geocoder
import android.location.Location
import android.location.LocationListener
import android.location.LocationManager
import androidx.core.app.ActivityCompat
import com.cash.app.application.MyApplication
import com.cash.app.constant.AppConstant.K_APP_ADDRESS
import com.cash.app.constant.AppConstant.K_APP_LATITUDE
import com.cash.app.constant.AppConstant.K_APP_LONGITUDE
import java.util.Locale

object AppLocationUtils : LocationListener {

    private const val TAG = "AppLocationUtils"
    private lateinit var locationManager: LocationManager

    fun startLocate() {

        locationManager =
            MyApplication.appContext.getSystemService(Context.LOCATION_SERVICE) as LocationManager

        val provider = LocationManager.NETWORK_PROVIDER

        if (!locationManager.isProviderEnabled(provider)) {
            TLog.w("NETWORK_PROVIDER is not enabled", TAG)
            return
        }

        val permission = Manifest.permission.ACCESS_COARSE_LOCATION

        if (ActivityCompat.checkSelfPermission(
                MyApplication.appContext, permission
            ) != PackageManager.PERMISSION_GRANTED
        ) {
            TLog.w("ACCESS_COARSE_LOCATION is not GRANTED", TAG)
            return
        }

        try {
            locationManager.requestLocationUpdates(
                provider, 3000, 10f, this
            )

            val lastLocation = locationManager.getLastKnownLocation(provider)
            lastLocation?.let {
                updateLocationInfo(it)
            }
        } catch (e: SecurityException) {
            e.printStackTrace()
            TLog.e("startLocate Exception", TAG, e)
        }
    }

    override fun onLocationChanged(location: Location) {
        updateLocationInfo(location)
    }

    private fun updateLocationInfo(location: Location) {
        val accuracy = if (location.hasAccuracy()) location.accuracy else "unknown"
        val info =
            "Info=latitude: ${location.latitude}," + "longitude: ${location.longitude}," +
                    "accuracy:" + "$accuracy meters," + "provider: " +
                    "${location.provider}," + "time: ${java.util.Date(location.time)}"

        TLog.d("Location $info", TAG)
        SpUtils.put(K_APP_LATITUDE, location.latitude.toString())
        SpUtils.put(K_APP_LONGITUDE, location.longitude.toString())
        getAddressFromLocation(location)

        // stop locate
        locationManager.removeUpdates(this)
    }

    private fun getAddressFromLocation(location: Location) {
        val geocoder = Geocoder(MyApplication.appContext, Locale.getDefault())
        try {
            val addresses = geocoder.getFromLocation(
                location.latitude, location.longitude, 1
            )
            TLog.d("get addresses $addresses", TAG)
            addresses?.firstOrNull()?.let { address ->
                if (address.maxAddressLineIndex >= 0) {
                    val ad = address.getAddressLine(0)
                    TLog.d("save address=$ad ", TAG)
                    SpUtils.put(K_APP_ADDRESS, ad)
                }
            }
        } catch (e: Exception) {
            e.printStackTrace()
            TLog.e("get address Exception", TAG, e)
        }
    }
}